﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PulseLibrary;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace PulsePrototype.PulseManagers
{
    public class RenderManager : BaseManager
    {
        private SpriteBatch spriteBatch;
        private String currentCameraEntityName = Common.RootEntityName;
        private Texture2D pixelDebugTexture;
        private SpriteFont debugFont;

        public GraphicsDeviceManager Graphics
        {
            get { return this.Game.Graphics; }
            set { this.Game.Graphics = value; }
        }

        public GraphicsDevice GraphicsDevice
        {
            get { return this.Game.GraphicsDevice; }
        }

        public SpriteBatch SpriteBatch
        {
            get { return spriteBatch; }
        }

        protected override String GetName()
        {
            return "Render";
        }

        public RenderManager(Game1 game)
            : base(game)
        {
            Initialize();
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        public override void LoadContent()
        {
            pixelDebugTexture = Game.Content.Load<Texture2D>("pixel");
            debugFont = Game.Content.Load<SpriteFont>("font");

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = Game.SpriteBatch;
        }

        public override void Draw(GameTime gameTime)
        {
            SceneManager sceneMgr = this.Game.GamePlayScreen1.GetManager("Scene") as SceneManager;
            if (null == sceneMgr)
            {
                throw new Exception("Scene manager not registered properly to the game engine");
            }

            BaseEntity cameraEntity = sceneMgr.GetEntity(currentCameraEntityName);
            if (null == cameraEntity)
            {
                throw new Exception("A camera entity must always exist if we are trying to render a scene");
            }

            CameraComponent camComp = cameraEntity.GetComponent("Camera") as CameraComponent;
            if (null == camComp)
            {
                throw new Exception("An entity was designated as a camera but never given a camera component");
            }

            List<RenderDescription> renderDescriptions = new List<RenderDescription>();

            // Get all entities in the scene
            Dictionary<string, BaseEntity> entities = sceneMgr.Entities;

            // TODO: Take each renderDescription and draw the animations inside them.
            spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null,
                null, null, camComp.getTransformation(Graphics));

            // This Draw method doesn't actually draw, but rather gets each RenderDescription
            // and puts them into the "renderDescription" list.
            foreach (KeyValuePair<string, BaseEntity> pair in entities)
            {
                (pair.Value).Draw(gameTime, renderDescriptions);
            }

            foreach (RenderDescription rDesc in renderDescriptions)
            {
                if (rDesc.drawWithVector == true)
                spriteBatch.Draw(rDesc.texture, rDesc.position.ToVector2(), null,
                    Color.White * rDesc.transparency, rDesc.rotation, rDesc.origin, rDesc.scale,
                    SpriteEffects.None, 0f);
                else
                    spriteBatch.Draw(rDesc.texture, rDesc.Destination, null,
                    Color.White * rDesc.transparency, rDesc.rotation, rDesc.origin,
                    SpriteEffects.None, 0f);

            }

            spriteBatch.End();

            if (DebugSettings.RenderDebug)
            {
                spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, 
                    null, null, null, null, camComp.getTransformation(Graphics));

                foreach (RenderDescription rDesc in renderDescriptions)
                {  
                    Vector2 origin = new Vector2(
                        (float)pixelDebugTexture.Bounds.Width  / 2f, 
                        (float)pixelDebugTexture.Bounds.Height / 2f);

                    spriteBatch.Draw(pixelDebugTexture, rDesc.Destination, null, 
                        Color.Red * 0.2f, rDesc.rotation, origin, 
                        SpriteEffects.None, 0f);

                    String id = rDesc.ParentComponent.Parent.UniqueID.ToString();

                    spriteBatch.DrawString(debugFont, id + ": " + rDesc.ParentComponent.Parent.Name,
                        rDesc.position.ToVector2() - rDesc.origin, Color.White);
                }
            
                spriteBatch.End();
            }
        }


    }
}
